﻿namespace WpfDevelopment.MVVM.Tests
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    public class CommunicationBusTests
    {
        [TestClass]
        public class Register
        {
            [TestMethod, ExpectedException(typeof(ArgumentNullException))]
            public void Must_throw_exception_if_message_is_null()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                sut.Register<string>(null, new Action<object>(f => { var foo = string.Empty; }));

                // Assert => exception is thrown
            }

            [TestMethod, ExpectedException(typeof(ArgumentNullException))]
            public void Must_throw_exception_if_action_is_null()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                sut.Register("testMessage", null);

                // Assert => exception is thrown
            }

            [TestMethod, ExpectedException(typeof(ArgumentNullException))]
            public void Must_throw_exception_if_action_target_is_null()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                sut.Register("testMessage", new Action<object>(f => { }));

                // Assert => exception is thrown
            }
        }

        [TestClass]
        public class Notify
        {
            [TestMethod, ExpectedException(typeof(ArgumentNullException))]
            public void Must_throw_exception_if_message_is_null()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                sut.Notify<string>(null, null);

                // Assert => exception is thrown
            }

            [TestMethod]
            public void Must_notify_one_listener_if_subscribed()
            {
                // Arrange
                var sut = new CommunicationBus();
                bool notified = false;
                sut.Register("testMessage", f => notified = true);

                // Act
                sut.Notify("testMessage", null);

                // Assert
                Assert.IsTrue(notified);
            }

            [TestMethod]
            public void Must_notify_all_listener_that_are_subscribed()
            {
                // Arrange
                var sut = new CommunicationBus();
                bool notified1 = false,
                        notified2 = false,
                        notified3 = false;
                sut.Register("testMessage", f => notified1 = true);
                sut.Register("testMessage", f => notified2 = true);
                sut.Register("testMessage", f => notified3 = true);

                // Act
                sut.Notify("testMessage", null);

                // Assert
                Assert.IsTrue(notified1 == notified2 == notified3 == true);
            }

            [TestMethod]
            public void Must_only_notify_listeners_that_are_subscribed_to_the_message()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                bool notified1 = false,
                        notified2 = false,
                        notified3 = false,
                        notified4 = false,
                        notified5 = false;
                sut.Register("testMessage", f => notified1 = true);
                sut.Register("otherMessage", f => notified2 = true);
                sut.Register("testMessage", f => notified3 = true);
                sut.Register(true, f => notified4 = true);
                sut.Register(new object(), f => notified5 = true);

                // Assert
                Assert.IsTrue(notified1 == notified3 == true);
                Assert.IsTrue(notified2 == notified4 == notified5 == false);
            }

            [TestMethod]
            public void Must_be_able_to_notify_when_there_are_no_subscribers()
            {
                // Arrange
                var sut = new CommunicationBus();

                // Act
                sut.Notify("testMessage", null);

                // Assert = no exception is thrown
            }
        }
    }
}
